#include <string.h>
#include "gkt_malloc.h"
#include "gkt_crc.h"
#include "gkt_rfid.h"
#include "window_common.h"

#if WINDOW_VENDOR_IMAGE_ENABLE

#ifdef GKT_CONFIG_WINDOW_VENDOR_IMAGE_RFID_KEY
static uint8_t s_rfid_card_key[] = { GKT_CONFIG_WINDOW_VENDOR_IMAGE_RFID_KEY };
#else
static uint8_t s_rfid_card_key[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
#endif

const window_vendor_image_s *window_vendor_get_image(void)
{
	const window_vendor_image_s *image;

	image = &gp_window_unreset_data->vendor_image;
	gkt_trace("window_vendor: [GET] magic(0x%x), width(%u), height(%u)\n",
					image->magic, image->width, image->height);

	if ((WINDOW_VENDOR_IMAGE_MAGIC == image->magic)
		&& image->width && (image->width <= WINDOW_VENDOR_IMAGE_MAX_WIDTH)
		&& image->height && (image->height <= WINDOW_VENDOR_IMAGE_MAX_HEIGHT))
	{
		return image;
	}

	return NULL;
}

#define CARD_SECTOR_MANUFACTURER	0
#define CARD_SECTOR_MAX	16
#define CARD_BLOCK_AUTH	3
#define CARD_BLOCK_MAX	4
#define CARD_BLOCK_SIZE	16

#define CARD_BLOCK_ADDR(sector_id, block_id)	\
	(((sector_id) * CARD_BLOCK_MAX) + (block_id))

static int window_vendor_read_block_data(
				gkt_rfid_info_s *rfid_info,
				uint32_t block_index, void *buffer)
{
	uint32_t sector_id, block_id, block_addr;
	int retval;

	sector_id = (block_index / CARD_BLOCK_AUTH) + 1;
	block_id = block_index % CARD_BLOCK_AUTH;
	block_addr = CARD_BLOCK_ADDR(sector_id, block_id);

	retval = gkt_rfid_auth_state(GKT_RFID_AUTH_A_KEY,
					(uint8_t)block_addr, rfid_info->id, 
					s_rfid_card_key);
	if (GKT_SUCCESS == retval)
		retval = gkt_rfid_read(block_addr, buffer);
	else {
		gkt_error("window_vendor: auth (%u - %u) failed %d\n", 
						sector_id, block_id, retval);
	}

	return retval;
}

int window_vendor_update_image(gkt_rfid_info_s *rfid_info)
{
	window_vendor_image_header_s image_header;
	uint8_t *image_data;
	uint32_t block_index;
	uint32_t image_data_size, aligned_image_data_size, offset;
	uint16_t crc16;
	int retval;

	/* read image header */
	block_index = 0;

#if defined(GKT_CONFIG_RFID_QUERY_MODE_ENABLE) && GKT_CONFIG_RFID_QUERY_MODE_ENABLE	
	retval = gkt_rfid_get_info(rfid_info, 1);
	if (retval != GKT_SUCCESS) {
		retval = gkt_rfid_get_info(rfid_info, 1);
		if (retval != GKT_SUCCESS)
			gkt_printf("vendor_update_image err\n");
	}
	gkt_rfid_control(GKT_RFID_CTRL_DISABLE, GKT_RFID_EXT_DATA_TRANSMISSION);
#endif	
	retval = window_vendor_read_block_data(rfid_info,
					block_index, (void *)&image_header);
	if (retval != GKT_SUCCESS) {		
#if defined(GKT_CONFIG_RFID_QUERY_MODE_ENABLE) && GKT_CONFIG_RFID_QUERY_MODE_ENABLE	
		gkt_rfid_antenna_off();
		gkt_rfid_control(GKT_RFID_CTRL_ENABLE, GKT_RFID_EXT_DATA_NONE);
#endif
		gkt_error("window_vendor: [UDT] read header block failed %d\n", retval);
		return retval;
	}

	gkt_trace("window_vendor: [UDT] magic(0x%08x), pf(%u), dmf(%u)\n",
				image_header.magic, image_header.pixel_format,
				image_header.dit_matrix_format);
	gkt_trace("window_vendor: [UDT] width(0x%04x), height(0x%04x), crc(0x%04x)\n",
				image_header.width,
				image_header.height, image_header.crc16);

	/* correct image header? */
	if ((image_header.magic != WINDOW_VENDOR_IMAGE_MAGIC)
		|| (image_header.pixel_format != GKT_SCREEN_PF_MONOCHROME)
		|| (image_header.dit_matrix_format != GKT_SCREEN_DMF_COL_ROW)
		|| !image_header.width || (image_header.width > WINDOW_VENDOR_IMAGE_MAX_WIDTH)
		|| !image_header.height || (image_header.height > WINDOW_VENDOR_IMAGE_MAX_HEIGHT))
	{
#if defined(GKT_CONFIG_RFID_QUERY_MODE_ENABLE) && GKT_CONFIG_RFID_QUERY_MODE_ENABLE	
		gkt_rfid_antenna_off();
		gkt_rfid_control(GKT_RFID_CTRL_ENABLE, GKT_RFID_EXT_DATA_NONE);
#endif
		gkt_trace("window_vendor: [UDT] invalid header, unsupport!\n");
		return GKT_ENOTSUPPORT;
	}

	image_data_size = WINDOW_VENDOR_IMAGE_SIZE(image_header.width, image_header.height);
	aligned_image_data_size = gkt_aligned(image_data_size, CARD_BLOCK_SIZE);
	image_data = (uint8_t *)gkt_malloc(aligned_image_data_size);
	if (!image_data) {		
#if defined(GKT_CONFIG_RFID_QUERY_MODE_ENABLE) && GKT_CONFIG_RFID_QUERY_MODE_ENABLE	
		gkt_rfid_antenna_off();
		gkt_rfid_control(GKT_RFID_CTRL_ENABLE, GKT_RFID_EXT_DATA_NONE);
#endif
		gkt_error("window_vendor: [UDT] alloc image buff failed!\n");
		return GKT_ENOMEMORY;
	}

	/* read image data */
	offset = 0;
	block_index++;
	do {
		retval = window_vendor_read_block_data(rfid_info,
						block_index, &image_data[offset]);
		if (retval != GKT_SUCCESS) {	
#if defined(GKT_CONFIG_RFID_QUERY_MODE_ENABLE) && GKT_CONFIG_RFID_QUERY_MODE_ENABLE	
			gkt_rfid_antenna_off();
			gkt_rfid_control(GKT_RFID_CTRL_ENABLE, GKT_RFID_EXT_DATA_NONE);
#endif
			gkt_error("window_vendor: [UDT] read block %u failed %d\n", block_index, retval);
			goto done;
		}

		block_index++;
		offset += CARD_BLOCK_SIZE;
	} while (offset < aligned_image_data_size);

#if defined(GKT_CONFIG_RFID_QUERY_MODE_ENABLE) && GKT_CONFIG_RFID_QUERY_MODE_ENABLE	
	gkt_rfid_antenna_off();
	gkt_rfid_control(GKT_RFID_CTRL_ENABLE, GKT_RFID_EXT_DATA_NONE);
#endif

	/* check image data crc */
	crc16 = gkt_crc16_ccitt_false(image_data, image_data_size);
	if (crc16 != image_header.crc16) {
		gkt_error("window_vendor: crc(0x%x) not correct.\n", crc16);
		retval = GKT_EUNMATCHED;
		goto done;
	}

	/* save image */
	gp_window_unreset_data->vendor_image.magic = 0;
	memcpy(gp_window_unreset_data->vendor_image.data, image_data, 
				image_data_size);
	while (image_data_size < WINDOW_VENDOR_IMAGE_MAXSIZE) {
		gp_window_unreset_data->vendor_image.data[image_data_size] = 0;
		image_data_size++;
	}
	gp_window_unreset_data->vendor_image.width = image_header.width;
	gp_window_unreset_data->vendor_image.height = image_header.height;
	gp_window_unreset_data->vendor_image.magic = WINDOW_VENDOR_IMAGE_MAGIC;

	/* update */
	window_data_save();

done:
	if (image_data)
		gkt_free(image_data);

	return retval;
}

#endif

